package com.waterfairy.http;

import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;

import com.waterfairy.http.exception.HttpExceptionUtils;
import com.waterfairy.http.response.BaseListBean;
import com.waterfairy.http.response.BaseListPageResponse;
import com.waterfairy.http.response.BaseListResponse;
import com.waterfairy.http.response.IBaseResponse;
import com.waterfairy.utils.GsonUtils;
import com.waterfairy.utils.PackageUtils;
import com.waterfairy.utils.ToastUtils;

import java.util.ArrayList;

import retrofit2.Call;
import retrofit2.Callback;

/**
 * Created by water_fairy on 2017/4/9.
 */

public abstract class BaseCallback<T> implements Callback<T>, LifecycleObserver {
    private final String TAG = "baseCallback";
    private boolean isDestroy;
    @Nullable
    private Lifecycle lifecycle;
    private boolean showToast = true;

    private LifecycleEventObserver lifecycleEventObserver = new LifecycleEventObserver() {
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            //未销毁 且 当前事件为销毁 且 lifecycle!=null
            if (!isDestroy && (isDestroy = Lifecycle.Event.ON_DESTROY == event) && lifecycle != null) {
                lifecycle.removeObserver(lifecycleEventObserver);
                lifecycle = null;
                lifecycleEventObserver = null;
            }
        }
    };

    private BaseCallback() {
    }


    public BaseCallback(Lifecycle lifecycle) {
        this(lifecycle, true);
    }

    public BaseCallback(@Nullable Lifecycle lifecycle, Boolean showToast) {
        if (lifecycle != null) {
            lifecycle.addObserver(lifecycleEventObserver);
        }
        this.lifecycle = lifecycle;
        this.showToast = showToast;
    }

    public abstract void onSuccess(@NonNull T t);

    public abstract void onFailed(int code, @NonNull String message);

    @Override
    public void onResponse(@NonNull Call<T> call, @NonNull retrofit2.Response<T> response) {
        handleData(call, response);
    }

    @Override
    public void onFailure(@NonNull Call<T> call, @NonNull Throwable throwable) {
        if (lifecycle == null || isDestroy) {
            return;
        }
        HttpExceptionUtils.ResponseThrowable responseThrowable = HttpExceptionUtils.handleException(throwable);
        if (showToast) ToastUtils.show(responseThrowable.message);
        onFailed(responseThrowable.code, responseThrowable.message);
        Log.i(TAG, "error: " + responseThrowable.code + " -- " + responseThrowable.message);
    }

    private void handleData(Call<T> call, retrofit2.Response<T> response) {
        int code = response.code();//200;400;401
        String showMessage = null;
        if (code == 200) {
            T body = response.body();
            if (PackageUtils.isTestRelease()) {
                logResult(call, body);
            }

            if (lifecycle == null || isDestroy) {
                return;
            }

            IBaseResponse baseResponse = null;
            if (body instanceof IBaseResponse) {
                baseResponse = (IBaseResponse) body;

                boolean isListDataOk = true;//返回list时 判断是否有数据 没有数据返回false
                if (body instanceof BaseListPageResponse) {
                    BaseListBean<T> data = ((BaseListPageResponse<T>) body).getData();
                    ArrayList<T> currentPageDataList = null;
                    if (data == null || (currentPageDataList = ((BaseListPageResponse<T>) body).getData().getRecords()) == null || currentPageDataList.size() == 0) {
                        isListDataOk = false;
                    }
                }
                if (body instanceof BaseListResponse) {
                    ArrayList<T> listData = ((BaseListResponse<T>) body).getData();
                    if (listData == null || listData.size() == 0) {
                        isListDataOk = false;
                    }
                }
                if (isListDataOk && HttpResultCode.HTTP_RESULT_SUCCESS == baseResponse.getResultCode()) {
                    //返回成功
                    onSuccess(body);
                } else {
                    //返回错误信息
                    showMessage = baseResponse.getMessage();
                    int resultCode = baseResponse.getResultCode();
                    if (resultCode == 0) {
                        resultCode = HttpResultCode.HTTP_RESULT_UN_KNOW;
                    }
                    if (TextUtils.isEmpty(showMessage)) {
                        showMessage = "未获取到数据";
                    }
                    if (!isListDataOk && resultCode != HttpResultCode.HTTP_RESULT_TOKEN_2) {
                        resultCode = HttpResultCode.HTTP_RESULT_NO_RESULT;
                        showMessage = "未查询到数据";
                    }
                    onFailed(resultCode, showMessage);
                }
            } else {
                //未使用IBaseResponse 接口的自行判断
                onSuccess(body);
            }
        } else {
            if (PackageUtils.isTestRelease()) {
                Log.i(TAG, "handleData: " + code);
            }
            showMessage = "未获取到数据";
            onFailed(code, showMessage);
        }
        if (showToast && !TextUtils.isEmpty(showMessage)) {
            ToastUtils.show(showMessage);
        }
    }

    private void logResult(Call<T> call, T body) {
        int perLen = 100;
        if (body != null) {
            String jsonResult = GsonUtils.objectToJson(body);
            if (!TextUtils.isEmpty(jsonResult)) {
                Log.i("response", "▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ ");
                Log.i("response", " ►  " + call.request().url());
                int lines = jsonResult.length() / perLen + (jsonResult.length() % perLen == 0 ? 0 : 1);
                for (int i = 0; i < lines; i++) {
                    int start = i * perLen;
                    int end = start + perLen;
                    if (end > jsonResult.length()) {
                        end = jsonResult.length();
                    }
                    String itemJson = jsonResult.substring(start, end);
                    Log.i("response", " ►  " + itemJson);
                }
                Log.i("response", "▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ ");

            }
        }
    }
}
